/***************************************************************************
 创建者: 华磊
 开始时间: 2020.8.14
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) hualei 2020.5.8 类的具体实现代码编写

 版本说明
 V1.7 -2019.1.8 HUALEI 根据欧盛第一次测试改进。版本信息写在login.cpp 第126行.各个库没有单独的版本号。
 V1.7 -2019.1.11 HUALEI  改进connect方式为Qt::BlockingQueuedConnection，gsoap如果一个请求还没有等到回应，
 另外一个请求也发出了，可能会导致一直等待那个请求。仅仅ｇｓｏａｐ接收ｓｌｏｔ才用Qt::BlockingQueuedConnection.
 ***************************************************************************/
#include "mainwindow.h"
#include <QApplication>
#include <QObject>
#include <QTextCodec>
#include <QThread>
#include <QMetaType>
#include <QFontDatabase>
#include "../mapView/mapview.h"
#include "../agvSetView/agvsetdialog.h"
#include "../FtpManage/ftpmanage.h"
#include "../FileManage/filemanage.h"
#include "../FileManageDelegate/filemanagedelegate.h"
#include "../ProgramLanguageTranslate/programlanguagetranslate.h"
#include "../DeviceDriver/devicedriver.h"
#include "../JoyStickFunction/joystickdelegate.h"
#include "connectionfunction.h"
#include "../beltTrackView/belttrackview.h"
#include "../fleetDebugView/fleetdebugview.h"
#include "../WindowShowManage/windowshowmanage.h"
#include "../LaserCameraConfigView/lasercameraconfigview.h"
#include "../AxisSettingView/axissettingview.h"
#include "../CoupleControlView/couplecontrolview.h"
#include "virtualkeyboard.h"

//版本号目前寄存于此
#define D_HMI_VERSION "V2.98-2022.3.22"

FileData fileData;
FleetDebugView *g_fleetDebugView=NULL;
CoupleControlView *g_coupleControlView=NULL;
AxisSettingView *g_axisSettingView=NULL;
BeltTrackView *g_beltTrackView=NULL;
LaserCameraConfigView *g_laserCameraConfigView=NULL;
GlobalData *g_globalData=NULL;
GlobalData *g_ioData=NULL;
MainWindow *g_mainWindow=NULL;
WindowShowManage *g_windowShowManage=NULL;
Delegate *loginDelegate=NULL;
FtpManage *ftpManage=NULL;
MoveOperation *moveOperation=NULL;
CommunicateNormalDelegate *communicateNormalThread=NULL;
CommunicateSaveDelegate *communicateSaveThread=NULL;
CommunicateUpdateDelegate *communicateThread=NULL;
CommunicateUpdateDelegate *communicateThreadLV3=NULL;
JoyStickDelegate *joystickDelegate=NULL;
Login *loginView=NULL;
LeftView *leftView=NULL;
LeftViewDelegate *leftviewdelegate=NULL;
RightView *rightView =NULL;
RightViewDelegate *rightviewdelegate=NULL ;
#ifdef BUILD_ARM
DeviceDriver *deviceDriver=NULL;
#endif
BottomView *bottomView=NULL;
BottomViewDelegate *bottomviewdelegate=NULL;
MapDelegate *mapDelegate=NULL;
MapView *mapView=NULL;
TopView *topView=NULL;
TopViewDelegate *topviewdelegate=NULL;
MultiRobotControlDlg *multiRobotControlDlg=NULL;
LeftFun *leftFun=NULL;
LeftFunDelegate *leftfundelegate=NULL;
RightFun *rightFun=NULL;
RightFunDelegate *rightfundelegate=NULL;
RunView *runView =NULL;
RunDelegate *runDelegate=NULL;
JogView *jogView=NULL ;
JogDelegate *jogDelegate=NULL;
ProgramView *programView=NULL;
ProgramDelegate *programDelegate=NULL;
SystemStatus *ioStatusView=NULL;
SystemStatusDelegate *systemStatusDelegate=NULL;
MessageView *messageView=NULL;
MessageDelegate *messageDelegate =NULL;
ProgramFileView *programFileView=NULL;
ProgramFileDelegate *programFileDelegate=NULL;
FileManage *fileManage=NULL;
FileManageDelegate *fileManageDelegate=NULL;
HomeMenuView *homeMenuView=NULL;
HomeMenuDelegate *homeMenuDelegate=NULL;
RobotSettingDlg *robotSettingDlg=NULL;
AgvSetDialog *agvSetDialog=NULL;
MiddleViewDelegate *middleViewDelegate=NULL;
ProgramLanguageTranslate *programLanguageTranslate=NULL;

#define D_CPU_TEST 1

int getShowStyle()
{
    QSettings settings(D_SHOW_STYLE_PATH, QSettings::IniFormat);
    return settings.value("Common/styleId").toInt();
}

int getCobotFlag()
{
    QSettings settings(D_MODULE_CONFIG_PATH, QSettings::IniFormat);
    return settings.value("Module/coRobotFlag").toInt();
}

int get_allowMaxJogTime()
{
    QSettings settings(D_MODULE_CONFIG_PATH, QSettings::IniFormat);
    return settings.value("Module/allowMaxJogTime").toInt();
}

int main(int argc, char *argv[])
{
    //QApplication::setStyle("cleanlooks");//原本hmi的设置
    QApplication a(argc, argv);
    qDebug()<<"---------------"<<D_HMI_VERSION;
    //输入法
    qDebug()<<"current applicationDirPath: "<<QCoreApplication::applicationDirPath();
    qDebug()<<"current currentPath: "<<QDir::currentPath();
    QString workDir=QCoreApplication::applicationDirPath();
//    if(1)
//    {
//            auto keyboard = VirtualKeyBoard::getKeyboard();
//            keyboard->init(D_HMI_CHINESE_PYDB_PATH);
//    }

    //注册元结构
    qRegisterMetaType<std::vector<EcatBusDevInfo_gsoap> > ("std::vector<EcatBusDevInfo_gsoap>");
    qRegisterMetaType<MotionDebugInfo> ("MotionDebugInfo");
    qRegisterMetaType<ProgramEngineDebugInfo> ("ProgramEngineDebugInfo");

    //注册QVector<strcut Message>
    qRegisterMetaType<QVector<Message> > ("QVector<Message>");
    qRegisterMetaType<S_AXISGROUP_ZERO_INFORMATION> ("S_AXISGROUP_ZERO_INFORMATION");
    qRegisterMetaType<QVector<QString> > ("QVector<QString>");
    qRegisterMetaType<QVector<int> > ("QVector<int>");
    qRegisterMetaType<ComponentVersion>("ComponentVersion");
    qRegisterMetaType<CommRobotInfo>("CommRobotInfo");
    qRegisterMetaType<MoveParameter>("MoveParameter");
    qRegisterMetaType<CurrentRunFile>("CurrentRunFile");
    qRegisterMetaType<FileInfo>("FileInfo");
    qRegisterMetaType<PointPro>("PointPro");
    qRegisterMetaType<Message>("Message");
    qRegisterMetaType<PlRegStruct>("PlRegStruct");
    qRegisterMetaType<AxisLimit>("AxisLimit");
    qRegisterMetaType<HmiToolCoordinateInformation>("HmiToolCoordinateInformation");
    qRegisterMetaType<HmiUserCoordinateInformation>("HmiUserCoordinateInformation");
    qRegisterMetaType<QVector<HmiToolCoordinateInformation> >("QVector<HmiToolCoordinateInformation>");
    qRegisterMetaType<QVector<HmiUserCoordinateInformation> >("QVector<HmiUserCoordinateInformation>");
    qRegisterMetaType<ReturnRegisterStatus>("ReturnRegisterStatus");
    qRegisterMetaType<ControllerIpGroupInfo>("ControllerIpGroupInfo");
    qRegisterMetaType<std::vector<ProgramEngineDebugInfo> >("std::vector<ProgramEngineDebugInfo>");
    qRegisterMetaType<TaskManagerInfo>("TaskManagerInfo");
    qRegisterMetaType<std::vector<TaskManagerInfo> >("std::vector<struct TaskManagerInfo>");

    //设置样式
    QString qss;
    QFile qssFile(D_QSS_PATH);
    qssFile.open(QFile::ReadOnly);
    if(qssFile.isOpen())
    {
        qss = QLatin1String(qssFile.readAll());
        qApp->setStyleSheet(qss);
        qssFile.close();
    }

    ftpManage = new FtpManage;      // 全局Ftp对象

    //**********编码,字体设定**********
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
    QTextCodec *codec = QTextCodec::codecForName( "UTF-8" );
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);
#else
    QTextCodec *codec = QTextCodec::codecForName( "UTF-8" );
    QTextCodec::setCodecForLocale(codec);
#endif

#ifdef BUILD_ARM
//    int nIndex = QFontDatabase::addApplicationFont("/tcrwork/linuxControllerHmi/trunk/hmiController/fonts/simhei.ttf");
    int nIndex = QFontDatabase::addApplicationFont("/agvwork/AgvHmi/baseBag/tool/simhei.ttf");
    if (nIndex != -1)
    {
        QStringList strList(QFontDatabase::applicationFontFamilies(nIndex));
        if (strList.count() > 0)
        {
            QFont fontThis(strList.at(0));
            fontThis.setPointSize(9);
            a.setFont(fontThis);
        }
    }
#endif

    //**********global数据初始化**********
    g_globalData=new GlobalData;
    g_ioData=new GlobalData;

    /************* 实例化程序语言翻译类 ************/
    programLanguageTranslate = new ProgramLanguageTranslate;

    //**********gsoap通信初始化**********
    //update lv2定时
    communicateThread = new CommunicateUpdateDelegate;
    g_globalData->ioUpdateFlag = E_UPDATA_TYPE_COMMON;                //LV2
    communicateThread->hmiCommunicate->globalData = g_globalData;
    communicateThread->hmiCommunicate->ioData= g_ioData;

    //update lv3 定时
//    communicateThreadLV3 = new CommunicateUpdateDelegate;
//    g_ioData->ioUpdateFlag = E_UPDATA_TYPE_NONE;                    //默认已经是0 通过mid中修改标志位获取lv3
//    communicateThreadLV3->hmiCommunicate->globalData = g_ioData;

    //普通操作
    communicateNormalThread = new CommunicateNormalDelegate;
    communicateNormalThread->hmiCommunicate->globalData = g_globalData;
    // 供GSOAP读取远程iomap文件使用
    communicateThread->communicateNormalDelegate = communicateNormalThread;
//    communicateThreadLV3->communicateNormalDelegate = communicateNormalThread;

    //安全操作
    communicateSaveThread = new CommunicateSaveDelegate;
    communicateSaveThread->hmiCommunicate->globalData = g_globalData;

    #ifdef D_USE_JOYSTIC
    joystickDelegate=new JoyStickDelegate(communicateSaveThread,communicateNormalThread,g_globalData);
    #endif

    //**********运动操作初始化*********
    moveOperation=new MoveOperation(g_globalData,get_allowMaxJogTime()) ;

    //styleId
    int styleId=getShowStyle();
    int coRobotFlag=getCobotFlag();

    //**********login界面初始化**********
    loginView = new Login(styleId,g_globalData);//,&mainWindow
    loginDelegate = new Delegate(communicateNormalThread,D_HMI_VERSION,g_globalData,g_ioData,loginView);

    //**********主界面,风格**********
    g_mainWindow=new MainWindow(styleId,g_globalData,g_ioData);

    //**********硬件驱动初始化**********
    a.installEventFilter(g_mainWindow);//安装事件过滤器

    #ifdef BUILD_ARM
    deviceDriver = new DeviceDriver(moveOperation,g_globalData,workDir);//非ARM状态下只实现热拔插
    g_mainWindow->deviceDriver = deviceDriver;
    #endif

    #ifdef BUILD_ARM
    //**********热拔插初始化**********
    HotplugWatcher ht;
    ht.globalData = g_globalData;
    #endif


    //update中会把子页面的语言也刷新
    loginView->updateShow();//建立语言槽后,updateShow中会控制delegate和mainWindow
    qDebug()<<"login init";

    //**********其他界面的初始化**********
    //主窗口左侧界面
    leftView = new LeftView(styleId);
    leftviewdelegate=new LeftViewDelegate(leftView);

    //主窗口右侧界面
    rightView = new RightView(styleId);
    rightviewdelegate = new RightViewDelegate(rightView,g_globalData);
    qDebug()<<"left right init";

    //主窗口底部界面
    bottomView=new BottomView(styleId);
    bottomviewdelegate=new BottomViewDelegate(bottomView,g_globalData,communicateNormalThread);
    qDebug()<<"button init";

#ifdef D_FOR_AGV
    mapDelegate=new MapDelegate(communicateNormalThread,g_globalData,communicateThread);
    mapView=new MapView(mapDelegate);
#endif

    //主窗口顶部界面
    topView = new TopView(styleId);
    topviewdelegate = new TopViewDelegate(topView,g_globalData,g_ioData,communicateNormalThread);
    multiRobotControlDlg=new MultiRobotControlDlg(communicateNormalThread,g_mainWindow);
    qDebug()<<"top init";

    //主窗口左侧 功能界面
    leftFun = new LeftFun(styleId);
    leftfundelegate = new LeftFunDelegate(communicateNormalThread,g_globalData,leftFun);

    //主窗口右侧 功能界面
    rightFun = new RightFun(styleId);
    rightfundelegate = new RightFunDelegate(rightFun,g_globalData);
    qDebug()<<"left right fun init";

    //中间窗口-运程
    runView = new RunView(styleId);
    runDelegate = new RunDelegate(communicateNormalThread, runView,g_globalData,g_ioData,moveOperation,
                                                                        programLanguageTranslate);
    qDebug()<<"run init";

    //中间窗口-寸动
    jogView = new JogView(styleId,coRobotFlag,g_globalData);
    jogDelegate = new JogDelegate(moveOperation,jogView,g_globalData);
    qDebug()<<"jog init";

    //中间窗口-程序
    programView = new ProgramView(styleId,communicateNormalThread,g_globalData,
                                  moveOperation,g_ioData,mapView);
    programDelegate = new ProgramDelegate(communicateNormalThread,programLanguageTranslate
                                          ,programView,g_globalData,moveOperation,g_ioData,mapView);
    qDebug()<<"programView init";

    //中间窗口-IO (ioStatusView 等于 systemStatus)
    ioStatusView = new SystemStatus(styleId);
    systemStatusDelegate = new SystemStatusDelegate(communicateNormalThread,
                                              ioStatusView,g_globalData,g_ioData,moveOperation);
    qDebug()<<"io init";

    //中间窗口-信息
    messageView = new MessageView(styleId);
    messageDelegate = new MessageDelegate(messageView,g_globalData);
    qDebug()<<"msg init";

    //中间窗口-程序文件打开
    programFileView = new ProgramFileView(styleId,g_globalData);
    programFileDelegate = new ProgramFileDelegate(programFileView,g_globalData,communicateNormalThread);
    qDebug()<<"programFile init";

    // 文件管理界面
    fileManage = new FileManage(styleId);
    fileManageDelegate = new FileManageDelegate(fileManage);

    //中间窗口-菜单窗口
    homeMenuView = new HomeMenuView(styleId,communicateNormalThread,g_globalData,loginView,moveOperation);
    homeMenuDelegate = new HomeMenuDelegate(homeMenuView,g_globalData,moveOperation,communicateNormalThread);
    robotSettingDlg=new RobotSettingDlg(styleId,communicateNormalThread,homeMenuView);

    //agv设置窗口
    #ifdef D_FOR_AGV
    agvSetDialog = new AgvSetDialog(communicateNormalThread);
    #endif

    qDebug()<<"home menu init";

    //中间窗口-总策略 管理delegate
    middleViewDelegate = new MiddleViewDelegate(g_globalData,g_ioData,moveOperation,runView
                                                ,jogView,programView,ioStatusView,messageView,
                      programFileView,homeMenuView,bottomView,styleId,g_mainWindow,communicateNormalThread);

    //**********gsoap通信:移交线程与信号槽关联**********
    //LV2 LV-MSG　200ms网络延迟，会导致一次lv2更新要2000ms，关键问题是函数太多，导致数据需要多次来回．一个来回就加200ms延时．
//    QThread updateThread;                                   //
//    communicateThread->moveToThread(&updateThread);
//    updateThread.start();
    communicateThread->setUpdateTimerPeriod(200,1200,200);
    if(D_CPU_TEST)
    {
        communicateThread->start();
        qDebug()<<"communicateThread start";
    }

//    communicateThread->timerOrder->start(GSOAP_UPDATE);

    //LV3
//    QThread updateLV3Thread;                                //
//    communicateThreadLV3->moveToThread(&updateLV3Thread);
//    updateLV3Thread.start();
//    communicateThreadLV3->setUpdateTimerPeriod(350,1000,50);
//    communicateThreadLV3->timerOrder->start(GSOAP_UPDATE_400);

    //普通
    QThread normalThread;                                   //非指针类型可行,没有内存泄露情况
    communicateNormalThread->moveToThread(&normalThread);
    if(D_CPU_TEST)
    {
        normalThread.start();
        qDebug()<<"normalThread start";
    }

    //安全
    QThread saveThread;                                     //非指针类型可行,没有内存泄露情况
    communicateSaveThread->moveToThread(&saveThread);
    if(D_CPU_TEST)
    {
        saveThread.start();
        qDebug()<<"saveThread start";
    }


    //**********界面显示 设置位置 大小**********
    leftView->setParent(g_mainWindow);
    rightView->setParent(g_mainWindow);
    topView->setParent(g_mainWindow);
    bottomView->setParent(g_mainWindow);
    leftFun->setParent(g_mainWindow);
    rightFun->setParent(g_mainWindow);

    runView->setParent(g_mainWindow);
    jogView->setParent(g_mainWindow);
    programView->setParent(g_mainWindow);//windows下面会导致一直卡蹲在这里。
    ioStatusView->setParent(g_mainWindow);
    messageView->setParent(g_mainWindow);
    programFileView->setParent(g_mainWindow);
    homeMenuView->setParent(g_mainWindow);

    //---------------------------------------------
    topView->show();
    //topView->setGeometry(g_mainWindow->rect().x(), g_mainWindow->rect().y(),600, 125);
    qDebug()<<"top show";

    leftView->show();
    rightView->show();
    bottomView->show();
    leftFun->show();
    rightFun->show();

    leftView->setGeometry(g_mainWindow->rect().x(), g_mainWindow->rect().y()+115,70, 340);
    rightView->setGeometry(g_mainWindow->rect().x()+525, g_mainWindow->rect().y()+125,70, 430);
    bottomView->setGeometry(g_mainWindow->rect().x()+70, g_mainWindow->rect().y()+715,460, 80);
    leftFun->setGeometry(g_mainWindow->rect().x(), g_mainWindow->rect().y()+480,70, 335);
    rightFun->setGeometry(g_mainWindow->rect().x()+525, g_mainWindow->rect().y()+575,70, 275);


    runView->show();
    runView->setGeometry(70,128,460,595);

    jogView->hide();
    jogView->setGeometry(70,128,460,595);

    programView->hide();
    programView->setGeometry(70,128,460,595);

    ioStatusView->hide();
    ioStatusView->setGeometry(70,130,460,595);

    messageView->hide();
    messageView->setGeometry(70,128,460,595);

    programFileView->hide();
    programFileView->setGeometry(70,128,460,595);

    homeMenuView->hide();
    homeMenuView->setGeometry(70,128,460,595);

    switch (styleId) {
    case 1:
        leftView->setGeometry(g_mainWindow->rect().x()+10, g_mainWindow->rect().y()+95,70, 340);
        leftFun->setGeometry(g_mainWindow->rect().x()+10, g_mainWindow->rect().y()+400,70, 335);
        rightView->setGeometry(800-70-13, g_mainWindow->rect().y()+80,70, 430);
        rightFun->setGeometry(800-70-13, g_mainWindow->rect().y()+460+65,70, 275);
        bottomView->setGeometry(g_mainWindow->rect().x()+100, 600-80,600, 80);

        jogView->setGeometry(100,95,600,440);
        runView->setGeometry(100,95,600,440);
        programView->setGeometry(100,95,610,440);
        ioStatusView->setGeometry(100,95,600,440);
        messageView->setGeometry(100,95,600,440);
        programFileView->setGeometry(100,95,600,440);
        homeMenuView->setGeometry(100,95,600,440);

        break;
    default:
        break;
    }


    //setParent 按先后顺序 登录页面显示于最上层,登陆完成后hide
#ifdef D_FOR_AGV
    g_windowShowManage=new WindowShowManage;
    g_windowShowManage->addWindow(loginView,"登录");
    g_windowShowManage->addWindow(g_mainWindow,"主窗口");
    g_windowShowManage->activeTab(0);
//        g_windowShowManage->addWindow(mapView,"图像地图");
#else
        loginView->setParent(g_mainWindow);
#endif


    loginView->show_dialog();

    //
    g_mainWindow->show();
    qDebug()<<"mainWindow show";//

    g_beltTrackView=new BeltTrackView(styleId,communicateNormalThread,g_globalData,homeMenuView);
    g_axisSettingView=new AxisSettingView(styleId,communicateNormalThread,g_mainWindow);
    g_fleetDebugView=new FleetDebugView(styleId,communicateNormalThread,g_mainWindow);
    g_laserCameraConfigView=new LaserCameraConfigView(styleId,communicateNormalThread,homeMenuView);
    g_coupleControlView=new CoupleControlView(styleId,communicateNormalThread,g_globalData,homeMenuView);

    ConnectionFunction tmpCommection;

    if(1)
    {
        return a.exec();
    }
    else
    {
        sleep(1000);
    }
}
